﻿using StockModel;
using TechnicalIndicators.DateBased;
using TechnicalIndicators.QuotationBased;
using Utils;
using System;

namespace StockAnalyst2.Chart
{
	internal class Generator
	{
		#region Attributes

		private ReadWriteLockedObservableCollection<Quotation> _currentSource;

		private readonly BarGenerator _lastValueBarGenerator;
		private readonly LastValueGenerator _lastValueGenerator;
		private readonly BarValueExtractor _barValueExtractor;
		private readonly BarValueExtractor _barValueExtractorA;
		private readonly MovingAverage _sma1;
		private readonly MovingAverage _sma1a;
		private readonly ExponentialAverage _ema1;
		private readonly Trix _trix;
		private readonly RatioOfChange _trixRatioOfChange;
		private readonly VolumeGenerator _volumeGenerator;
		private readonly Accumulator _volumeAccumulator;


		private readonly int _period;

		#endregion

		#region Properties

		public ChartData Data { get; private set; }

		#endregion

		#region Public Methods

		public Generator()
		{
			_period = 300; //5 minutes

			this.Data = new ChartData();

			_lastValueBarGenerator = new BarGenerator(this.Data.LastValueBar.Data);
			_lastValueGenerator = new LastValueGenerator();
			_barValueExtractor = new BarValueExtractor();
			_barValueExtractorA = new BarValueExtractor();
			_sma1 = new MovingAverage(this.Data.SMA1.Data);
			_sma1a = new MovingAverage(this.Data.SMA3.Data);
			_ema1 = new ExponentialAverage(this.Data.SMA2.Data);
			_trix = new Trix(this.Data.Trix.Data);
			_trixRatioOfChange = new RatioOfChange(this.Data.TrixRatioOfChange.Data);
			_volumeGenerator = new VolumeGenerator();
			_volumeAccumulator = new Accumulator(this.Data.Volume.Data);
		}

		public void CreateChart(ReadWriteLockedObservableCollection<Quotation> source)
		{
			this.Clear();

			_currentSource = source;

			_volumeGenerator.Source = _currentSource;
			_volumeGenerator.Start();

			_volumeAccumulator.Source = _volumeGenerator.Serie;
			_volumeAccumulator.Configure(_period);
			_volumeAccumulator.Start();

			_lastValueGenerator.Source = _currentSource;
			_lastValueGenerator.Configure(true);
			_lastValueGenerator.Start();

			_lastValueBarGenerator.Source = _lastValueGenerator.Serie;
			_lastValueBarGenerator.Configure(TimeSpan.FromSeconds(_period));
			_lastValueBarGenerator.Start();

			_barValueExtractor.Source = _lastValueBarGenerator.Serie;
			_barValueExtractor.Configure(BarToValueMode.Average);
			_barValueExtractor.Start();

			_barValueExtractorA.Source = _lastValueBarGenerator.Serie;
			_barValueExtractorA.Configure(BarToValueMode.Close);
			_barValueExtractorA.Start();

			_sma1.Source = _barValueExtractor.Serie;
			_sma1.Configure(3);
			_sma1.Start();

			_sma1a.Source = _barValueExtractorA.Serie;
			_sma1a.Configure(3);
			_sma1a.Start();

			_ema1.Source = _barValueExtractor.Serie;
			_ema1.Configure(2);
			_ema1.Start();

			_trix.Source = _barValueExtractor.Serie;
			_trix.Configure(9);
			_trix.Start();

			_trixRatioOfChange.Source = _trix.Serie;
			_trixRatioOfChange.Configure(1, true);
			_trixRatioOfChange.Start();
		}

		public void Clear()
		{
			_volumeGenerator.Clear();
			_volumeAccumulator.Clear();
			_lastValueGenerator.Clear();
			_lastValueBarGenerator.Clear();
			_barValueExtractor.Clear();
			_barValueExtractorA.Clear();
			_sma1.Clear();
			_sma1a.Clear();
			_ema1.Clear();
			_trix.Clear();
			_trixRatioOfChange.Clear();
		}

		#endregion

		#region Private Methods

		#endregion

	}
}
